package com.jin.webvideo.base.spring.resource;

import com.jin.webvideo.base.linkedfile.io.LinkedFileInputStream;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourceRegion;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.http.converter.ResourceHttpMessageConverter;
import org.springframework.http.converter.ResourceRegionHttpMessageConverter;
import org.springframework.util.Assert;
import org.springframework.util.StreamUtils;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistration;
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler;

import java.io.IOException;
import java.io.InputStream;

public class LinkedFileResourceHandlerRegistration extends ResourceHandlerRegistration {
    public LinkedFileResourceHandlerRegistration(String... pathPatterns) {
        super(pathPatterns);
    }

    @Override
    protected ResourceHttpRequestHandler getRequestHandler() {
        ResourceHttpRequestHandler handler = super.getRequestHandler();
        handler.setResourceRegionHttpMessageConverter(new VResourceRegionHttpMessageConverter());
        handler.setResourceHttpMessageConverter(new VResourceHttpMessageConverter());
        return handler;
    }

    class VResourceRegionHttpMessageConverter extends ResourceRegionHttpMessageConverter {
        @Override
        protected void writeResourceRegion(ResourceRegion region, HttpOutputMessage outputMessage) throws IOException {
            Assert.notNull(region, "ResourceRegion must not be null");
            HttpHeaders responseHeaders = outputMessage.getHeaders();
            long start = region.getPosition();
            long end = start + region.getCount() - 1L;
            long resourceLength = region.getResource().contentLength();
            end = Math.min(end, resourceLength - 1L);
            long rangeLength = end - start + 1L;
            responseHeaders.add("Content-Range", "bytes " + start + '-' + end + '/' + resourceLength);
            responseHeaders.setContentLength(rangeLength);
            InputStream in = region.getResource().getInputStream();
            try {
                // 与 ResourceRegionHttpMessageConverter 不同设置长度
                if (in instanceof LinkedFileResourceInputStream input) {
                    input.setResourceLength(rangeLength);
                }
                StreamUtils.copyRange(in, outputMessage.getBody(), start, end);
            }
            finally {
                try {
                    in.close();
                } catch (IOException var19) {
                    var19.printStackTrace();
                }
            }
        }
    }

    class VResourceHttpMessageConverter extends ResourceHttpMessageConverter {
        @Override
        protected void writeInternal(Resource resource, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
            super.writeInternal(resource, outputMessage);
        }
    }
}
